package parser;

import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import utils.Triplett;

public final class TagDB {

	private static final Repeatability R = Repeatability.REPEATABLE;
	private static final Repeatability NR = Repeatability.NON_REPEATABLE;
	private static final Repeatability U = Repeatability.UNKNOWN;

	private static HashMap<String, Tag> database = new HashMap<String, Tag>();
	private static TreeMap<String, Tag> pica3Map =
		new TreeMap<String, Tag>(new Pica3Comparator());
	private static TreeMap<String, Tag> picaPlusMap =
		new TreeMap<String, Tag>();

	public static class Pica3Comparator implements Comparator<String> {
		public Pica3Comparator() {
		}

		/*
		 * Damit Tags, die zu SWW gehören (380 ..) vor solchen einsortieren,
		 * die zu Titeldaten gehören (1000 ...).
		 */
		@Override
		public int compare(final String o1, final String o2) {
			int a1 = Integer.parseInt(o1);
			int a2 = Integer.parseInt(o2);
			return a1 - a2;
		}
	}

	/**
	 * Findet einen TagEnum zu einer Pica- oder Pica+ Feldkennzeichnung.
	 * 
	 * @param tag 	Pica3- oder Pica+-Feldkennzeichnung nicht null, nicht leer.
	 * 				Kann Leerzeichen vorne oder hinten enthalten.
	 * @return	Gültiger TagDB oder null.
	 */
	public static Tag findTag(final String tag) {
		if (tag == null)
			throw new IllegalArgumentException("tag ist null");
		String tagStr = tag.trim();
		if (tagStr.length() == 0)
			throw new IllegalArgumentException("tag enthält keinen Text");

		// Jetzt suchen:
		return database.get(tagStr);

	}

	private static void addTag(final Tag tag) {
		database.put(tag.pica3, tag);
		database.put(tag.picaPlus, tag);
		pica3Map.put(tag.pica3, tag);
		picaPlusMap.put(tag.picaPlus, tag);
	}

	/**
	 * Liefert zu einer Zeile ein Tripel aus Tag am Anfang, den Match und den Rest 
	 * (getrimmt).
	 * 
	 * @param line != null.
	 */
	public static Triplett<Tag, String, String> parseTag(String line) {
		if (line == null)
			throw new IllegalArgumentException();

		final Pattern tagP = Pattern.compile("^\\S{3,} +");
		Matcher m = tagP.matcher(line);
		if (m.find()) {
			String match = m.group().trim();
			Tag tag = findTag(match);
			if (tag == null)
				return null;
			// also was gefunden:
			int posRest = m.end();
			String rest = line.substring(posRest);

			return new Triplett<Tag, String, String>(tag, match, rest);
		}
		return null;

	}

	static {
		Tag newTag;
		//@formatter:off

		newTag =
			new Tag(
					"001",
					"001A",
					"Quelle und Datum der Ersterfassung",
					NR,
					"008",
					"Fixed-Length Data Elements");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", '0', "", U, ""));

		newTag =
			new Tag(
					"002",
					"001B",
					"Quelle und Datum der letzten Änderung",
					NR,
					"005",
					"Date and Time of Latest Transaction");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", '0', "", U, ""));
		
		newTag =
			new Tag(
					"003",
					"001D",
					"Quelle und Datum der letzten Statusvergabe",
					NR,
					"null",
					"");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", '0', "", U, ""));
		
		newTag =
			new Tag(
					"005",
					"002@",
					"Satzart",
					NR,
					"008; 079",
					"Fixed-Length Data Elements");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", '0', "", U, ""));
		
		newTag =
			new Tag(
					"006",
					"003U",
					"GND-Identifier",
					R,
					"024",
					"Other Standard Identifier");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "GND-URI", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen", NR, ""));
		
		newTag = new Tag("008", "004B", "Entitätencodierung", NR, "079", "");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Code", R, ""));
		newTag.repetitionChar = ';';
		
		newTag =
			new Tag("010", "008@", "Änderungscodierung", NR, "Leader", "");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Code", NR, ""));
		
		newTag =
			new Tag("011", "008A", "Teilbestandskennzeichen", NR, "079", "");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Code", R, ""));
		newTag.repetitionChar = ';';
		
		newTag = new Tag("012", "008B", "Nutzungskennzeichen", NR, "079", "");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Code", R, ""));
		newTag.repetitionChar = ';';
		
		newTag = new Tag("023", "007W", "SWD-Nr. im GKD-Satz", R, "null", "");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", '0', "SWD-Nummer", U, ""));
		
		newTag =
			new Tag(
					"024",
					"006Y",
					"Sonstige Standardnummern",
					R,
					"024",
					"Other Standard Identifier");
		addTag(newTag);
		// $S darf nicht eingegeben werden (30.11.2012)
		newTag.addIndicator(new Indicator(null, 'S', "Quelle/Code der", U, ""));
		newTag.addIndicator(new Indicator("-ohne-", '0', "Nummer/Code", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen", NR, ""));
		
		newTag = new Tag("028", "007R", "GKD-Nr. im SWD-Satz", R, "null", "");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", '0', "GKD-Nummer", U, ""));
		
		newTag =
			new Tag(
					"034",
					"037H",
					"Geografische Koordinaten",
					R,
					"034",
					"Coded Cartographic Mathematical Data");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'S', "Indikator", NR, ""));
		newTag.addIndicator(new Indicator(null, 'd', "Koordinaten - westlichster Längengrad", NR, ""));
		newTag.addIndicator(new Indicator(null, 'e', "Koordinaten - östlichster Längengrad", NR, ""));
		newTag.addIndicator(new Indicator(null, 'f', "Koordinaten - nördlichster Längengrad", NR, ""));
		newTag.addIndicator(new Indicator(null, 'g', "Koordinaten - südlichster Längengrad", NR, ""));
		newTag.addIndicator(new Indicator(null, '2', "Quelle", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen", NR, ""));
		
		newTag =
			new Tag(
					"035",
					"007K",
					"GND-Nummer",
					NR,
					"035",
					"System Control Number");
		addTag(newTag);
		// hier erzählt das Dokument "GND-Datenformat" Unfug:
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Präfix", NR, ""));
		newTag.addIndicator(new Indicator("/", '0', "GND-Nummer", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen", NR, ""));
		
		newTag =
			new Tag(
					"039",
					"007N",
					"Alte Normnummer",
					R,
					"035",
					"System Control Number");
		addTag(newTag);
		// wie oben!
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Präfix", NR, ""));
		newTag.addIndicator(new Indicator("/", '0', "Alte Normnummer", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen", NR, ""));
		
		newTag =
			new Tag(
					"043",
					"042B",
					"Ländercode nach ISO 3166",
					NR,
					"043",
					"Geographic Area Code");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Ländercode", R, ""));
		newTag.repetitionChar = ';';
		
		newTag =
			new Tag(
					"065",
					"042A",
					"GND Systematik",
					NR,
					"065",
					"Other Classification Number");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Notation", R, ""));
		newTag.repetitionChar = ';';
		
		newTag =
			new Tag(
					"083",
					"037G",
					"DDC-Notation",
					R,
					"083",
					"Dewey Decimal Classificaton Number");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'c', "DDC-Notation", NR, ""));
		newTag.addIndicator(new Indicator(null, 'd', "Determiniertheit", NR, ""));
		newTag.addIndicator(new Indicator(null, 't', "Zeitstempel der Notationsvergabe", NR, ""));
		newTag.addIndicator(new Indicator(null, 'g', "Zeitstempel der letzten Überprüfung", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen", NR, ""));
		
		newTag =
			new Tag("089", "037I", "Veraltete DDC-Notation", R, "089", "");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'c', "DDC-Notation", NR, ""));
		newTag.addIndicator(new Indicator(null, 'd', "Determiniertheit", NR, ""));
		newTag.addIndicator(new Indicator(null, 't', "Zeitstempel für „gültig seit“", NR, ""));
		newTag.addIndicator(new Indicator(null, 'g', "Zeitstempel für „gültig bis“", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen", NR, ""));
		
		newTag =
			new Tag(
					"100",
					"028A",
					"Person – Bevorzugter Name",
					NR,
					"100",
					"Heading - Personal Name");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, 'P', "Persönlicher Name", NR, ""));
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Nachname", NR, ""));
		newTag.addIndicator(new Indicator(", ", 'd', "Vorname", NR, ""));
		newTag.addIndicator(new Indicator(null, 'c', "Nachgestelltes Präfix", NR, ""));
		newTag.addIndicator(new Indicator(null, 'n', "Zählung", NR, ""));
		newTag.addIndicator(new Indicator(null, 'l', "Beiname, Gattungsname, Territorium, Titulatur", NR, ""));
		newTag.addIndicator(new Indicator(null, 'x', "Allgemeine Unterteilung", R, ""));
		newTag.addIndicator(new Indicator(null, 'g', "Zusatz", R, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen, Regelwerk", R, ""));
		
		newTag =
			new Tag(
					"110",
					"029A",
					"Körperschaft – Bevorzugter Name",
					NR,
					"110",
					"Heading - Corporate Name");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Hauptkörperschaft", NR, ""));
		newTag.addIndicator(new Indicator(null, 'b', "Untergeordnete Körperschaft", R, ""));
		newTag.addIndicator(new Indicator(null, 'n', "Zählung", R, ""));
		newTag.addIndicator(new Indicator(null, 'x', "Allgemeine Unterteilung", R, ""));
		newTag.addIndicator(new Indicator(null, 'g', "Zusatz", R, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen, Regelwerk", R, ""));
		
		newTag =
			new Tag(
					"111",
					"030A",
					"Kongress – Bevorzugter Name",
					NR,
					"111",
					"Heading - Meeting Name");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Hauptkongress", NR, ""));
		newTag.addIndicator(new Indicator(null, 'b', "Untergeordnete Einheit", R, ""));
		newTag.addIndicator(new Indicator(null, 'n', "Zählung", R, ""));
		newTag.addIndicator(new Indicator(null, 'd', "Datum", NR, ""));
		newTag.addIndicator(new Indicator(null, 'c', "Ort", NR, ""));
		newTag.addIndicator(new Indicator(null, 'x', "Allgemeine Unterteilung", R, ""));
		newTag.addIndicator(new Indicator(null, 'g', "Zusatz", R, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen, Regelwerk", R, ""));
		
		newTag =
			new Tag(
					"130",
					"022A",
					"Einheitstitel – Bevorzugter Name",
					NR,
					"130",
					"Heading - Uniform Title");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Titel eines Werks", NR, ""));
		newTag.addIndicator(new Indicator(null, 'f', "Entstehungsjahr eines Werks", NR, ""));
		newTag.addIndicator(new Indicator(null, 'm', "Besetzung im Musikbereich", R, ""));
		newTag.addIndicator(new Indicator(null, 'n', "Zählung eines Werks, des Teils/der Abteilung eines Werks", R, ""));
		newTag.addIndicator(new Indicator(null, 'o', "Angabe des Musikarrangements", NR, ""));
		newTag.addIndicator(new Indicator(null, 'p', "Titel des Teils/der Abteilung eines Werkes", R, ""));
		newTag.addIndicator(new Indicator(null, 'r', "Tonart", NR, ""));
		newTag.addIndicator(new Indicator(null, 's', "Version", NR, ""));
		newTag.addIndicator(new Indicator(null, 'x', "Allgemeine Unterteilung", R, ""));
		newTag.addIndicator(new Indicator(null, 'g', "Zusatz", R, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen, Regelwerk", R, ""));
		
		newTag =
			new Tag(
					"148",
					"060A",
					"Zeit  - wird nicht verwendet",
					NR,
					"148",
					"Heading - Chronological Term");
		addTag(newTag);
		
		newTag =
			new Tag(
					"150",
					"041A",
					"Sachbegriff – Bevorzugte Benennung",
					NR,
					"150",
					"Heading - Topical Term");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Sachbegriff", NR, ""));
		newTag.addIndicator(new Indicator(null, 'x', "Allgemeine Unterteilung", R, ""));
		newTag.addIndicator(new Indicator(null, 'g', "Zusatz", R, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen, Regelwerk", R, ""));
		
		newTag =
			new Tag(
					"151",
					"065A",
					"Geografikum – Bevorzugter Name",
					NR,
					"151",
					"Heading - Geographic Name");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Geografikum", NR, ""));
		newTag.addIndicator(new Indicator(null, 'x', "Allgemeine Unterteilung", R, ""));
		newTag.addIndicator(new Indicator(null, 'z', "Geografische Unterteilung", R, ""));
		newTag.addIndicator(new Indicator(null, 'g', "Zusatz", R, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen, Regelwerk", R, ""));
		
		newTag =
			new Tag(
					"169",
					"038L",
					"Markierung für das Match-und-Merge- Verfahren",
					NR,
					"null",
					"");
		addTag(newTag);
		// "GND-Datenformat" ist hier nicht korrekt. 
		newTag.addIndicator(new Indicator(null, 'a', "Angabe des Match-und- Merge-Kontingents", NR, ""));
		newTag.addIndicator(new Indicator(null, 'b', "Status der Prüfung", NR, ""));
		newTag.addIndicator(new Indicator(null, 'x', "Interne Protokollierung", NR, ""));
		newTag.addIndicator(new Indicator(null, '9', "Verknüpfungsnummer eines gefundenen Datensatzes", NR, ""));
		newTag.addIndicator(new Indicator(null, '8', "Expansion eines gefundenen Datensatzes", NR, ""));
		
		newTag =
			new Tag(
					"260",
					"041O",
					"Zu verknüpfende Schlagwörter in Hinweissätzen",
					R,
					"260",
					"Complex See Reference");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, '9', "Verknüpfungsnummer", NR, ""));
		newTag.addIndicator(new Indicator(null, '8', "Expansion eines gefundenen Datensatzes", NR, ""));
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Form-, Zeitschlagwort", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen, Regelwerk", NR, ""));
		
		newTag =
			new Tag("336", "032L", "Inhaltstyp", R, "336", "Content Type");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'b', "Code", R, ""));
		
		newTag = new Tag("337", "032M", "Medientyp", R, "339", "");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'b', "Code", R, ""));
		
		newTag = new Tag("338", "032N", "Datenträgertyp", R, "339", "");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'b', "Code", R, ""));
		
		newTag =
			new Tag(
					"372",
					"032Q",
					"Tätigkeitsbereich",
					R,
					"372",
					"Field of Activity");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, '9', "Verknüpfungsnummer", NR, ""));
		newTag.addIndicator(new Indicator(null, '8', "Expansion eines gefundenen Datensatzes", NR, ""));
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Sachbegriff", NR, ""));
		newTag.addIndicator(new Indicator(null, 'w', "Quelle der Information (ggfs. URI)", R, ""));
		newTag.addIndicator(new Indicator(null, 'Z', "Zeitl. Gültigkeit der Beziehung", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen", NR, ""));
		
		newTag =
			new Tag("375", "032T", "Geschlechtsangabe", NR, "375", "Gender");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Geschlecht", R, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen", NR, ""));
		
		newTag =
			new Tag(
					"377",
					"042C",
					"Sprachencode nach ISO 639-2/B",
					NR,
					"377",
					"Associated Language");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Code", R, ""));
		newTag.repetitionChar = ';';
		
		newTag =
			new Tag("380", "032W", "Form des Werks", R, "380", "Form of work");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, '9', "Verknüpfungsnummer", NR, ""));
		newTag.addIndicator(new Indicator(null, '8', "Expansion eines gefundenen Datensatzes", NR, ""));
		
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Form des Werks", NR, ""));
		
		newTag =
			new Tag(
					"382",
					"032X",
					"Besetzung im Musikbereich",
					NR,
					"382",
					"Medium of Performance");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, '9', "Verknüpfungsnummer", NR, ""));
		newTag.addIndicator(new Indicator(null, '8', "Expansion eines gefundenen Datensatzes", NR, ""));
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Darstellungsmedium (Term)", NR, ""));
		newTag.addIndicator(new Indicator(null, 'n', "Besetzungsstärke", NR, ""));
		newTag.addIndicator(new Indicator(null, 'p', "Alternative Besetzung", NR, ""));
		newTag.addIndicator(new Indicator(null, 's', "Gesamtbesetzungsstärke", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen", NR, ""));		
		
		newTag =
			new Tag(
					"383",
					"032Y",
					"Numerische Kennzeichnung eines Musikwerks",
					R,
					"383",
					"Numeric Designation of Musical Work");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Fortlaufende Zählung", R, ""));
		newTag.addIndicator(new Indicator(null, 'b', "Opus-Zählung", R, ""));
		newTag.addIndicator(new Indicator(null, 'c', "Zählung eines Werkverzeichnisses", R, ""));
		
		newTag = new Tag("384", "032Z", "Tonart", NR, "384", "Key");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Tonart des Werks", NR, ""));
		newTag.addIndicator(new Indicator(null, 'b', "Tonart der Fassung", NR, ""));
		
		newTag =
			new Tag(
					"400",
					"028@",
					"Person – Abweichender Name",
					R,
					"400",
					"See From Tracing - Personal Name");
		addTag(newTag);
		newTag =
			new Tag(
					"410",
					"029@",
					"Körperschaft – Abweichender Name",
					R,
					"410",
					"See From Tracing - Corporate Name");
		addTag(newTag);
		newTag =
			new Tag(
					"411",
					"030@",
					"Kongress – Abweichender Name",
					R,
					"411",
					"See From Tracing - Meeting Name");
		addTag(newTag);
		newTag =
			new Tag(
					"430",
					"022@",
					"Titel – Abweichender Name",
					R,
					"430",
					"See From Tracing - Uniform Title");
		addTag(newTag);
		newTag =
			new Tag(
					"448",
					"060@",
					"Zeit",
					Repeatability.UNKNOWN,
					"448",
					"See From Tracing - Chronological Term");
		addTag(newTag);
		newTag =
			new Tag(
					"450",
					"041@",
					"Sachbegriff – Abweichende Benennung",
					R,
					"450",
					"See From Tracing - Topical Term");
		addTag(newTag);
		newTag =
			new Tag(
					"451",
					"065@",
					"Geografikum – Abweichender Name",
					R,
					"451",
					"See From Tracing - Geographic Name");
		addTag(newTag);
		newTag =
			new Tag(
					"500",
					"028R",
					"Person – Beziehung",
					R,
					"500",
					"See Also From Tracing - Personal Name");
		addTag(newTag);
		newTag =
			new Tag(
					"510",
					"029R",
					"Körperschaft – Beziehung",
					R,
					"510",
					"See Also From Tracing - Corporate Name");
		addTag(newTag);
		newTag =
			new Tag(
					"511",
					"030R",
					"Kongress – Beziehung",
					R,
					"511",
					"See Also From Tracing - Meeting Name");
		addTag(newTag);
		newTag =
			new Tag(
					"530",
					"022R",
					"Einheitstitel – Beziehung",
					R,
					"530",
					"See Also From Tracing - Uniform Title");
		addTag(newTag);
		newTag =
			new Tag(
					"548",
					"060R",
					"Zeit – Beziehung",
					R,
					"548",
					"See Also From Tracing - Chronological Term");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Beginn einer Zeitspanne", NR, ""));
		newTag.addIndicator(new Indicator(null, 'b', "Ende einer Zeitspanne", NR, ""));
		newTag.addIndicator(new Indicator(null, 'c', "Zeitpunkt", NR, ""));
		newTag.addIndicator(new Indicator(null, 'd', "Ungefähre Zeitangabe", NR, ""));
		
		newTag =
			new Tag(
					"550",
					"041R",
					"Sachbegriff – Beziehung",
					R,
					"550",
					"See Also From Tracing - Topical Term");
		addTag(newTag);
		newTag =
			new Tag(
					"551",
					"065R",
					"Geografikum – Beziehung",
					R,
					"551",
					"See Also From Tracing - Geographic Name");
		addTag(newTag);
		newTag =
			new Tag(
					"667",
					"050C",
					"Redaktionelle Bemerkungen",
					R,
					"667",
					"Nonpublic General Note");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Freitext", NR, ""));
		newTag.addIndicator(new Indicator(null, '5', "Institution (=ISIL), die Feld in besonderer Art verwendet", R, ""));
		
		newTag =
			new Tag(
					"670",
					"050E",
					"Quellenangaben",
					R,
					"670",
					"Source Data Found");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Quelle", NR, ""));
		newTag.addIndicator(new Indicator(null, 'b', "Erläuternder Text", NR, ""));
		newTag.addIndicator(new Indicator(null, 'u', "URI", R, ""));
		
		newTag =
			new Tag(
					"675",
					"050F",
					"Negativ eingesehene Quellen",
					NR,
					"675",
					"Source Data Not Found");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Quelle", R, ""));
		newTag.repetitionChar = ';';
		
		newTag =
			new Tag(
					"678",
					"050G",
					"Biografische/historische Angaben",
					R,
					"678",
					"Biographical or Historical Data");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Quelle", R, ""));
		newTag.addIndicator(new Indicator(null, 'b', "Erläuternder Text", NR, ""));
		newTag.addIndicator(new Indicator(null, 'u', "URI", R, ""));
		
		newTag = new Tag("679", "050H", "Definitionen", R, "679", "");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Definition", NR, ""));
		
		newTag =
			new Tag(
					"680",
					"050D",
					"Benutzungshinweise",
					R,
					"680",
					"Public General Note");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Benutzungshinweis", NR, ""));
		
		newTag =
			new Tag(
					"682",
					"039I",
					"Nummer und bevorzugter Name bzw. bevorzugte Benennung des Zielsatzes bei Umlenkung von Datensätzen",
					NR,
					"682",
					"Deleted Heading Information");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, '9', "Verknüpfungsnummer", NR, ""));
		newTag.addIndicator(new Indicator(null, '8', "Expansion eines gefundenen Datensatzes", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkung", NR, ""));
		
		newTag =
			new Tag(
					"689",
					"039G",
					"Nummer und bevorzugter Name bzw. bevorzugte Benennung des Zielsatzes bei Aufspaltung von Datensätzen",
					NR,
					"682",
					"Deleted Heading Information");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Code für Art der Aufspaltung", U, ""));
		newTag.addIndicator(new Indicator(null, '9', "Verknüpfungsnummer", NR, ""));
		newTag.addIndicator(new Indicator(null, '8', "Expansion eines gefundenen Datensatzes", NR, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkung", NR, ""));
		
		newTag = new Tag("692", "046G", "Titelangaben", R, "692", "");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", 'a', "Titelangabe", NR, ""));
		
		newTag =
			new Tag(
					"700",
					"028P",
					"Person – Bevorzugter Name in einem anderen Datenbestand",
					R,
					"700",
					"Established Heading Linking Entry - Personal Name");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, 't', "Titel", NR, ""));
		newTag.inherited.add(pica3Map.get("130"));
		
		newTag =
			new Tag(
					"710",
					"029P",
					"Körperschaft – Bevorzugter Name in einem anderen Datenbestand",
					R,
					"710",
					"Established Heading Linking Entry - Corporate Name");
		addTag(newTag);
		newTag =
			new Tag(
					"711",
					"030P",
					"Kongress – Bevorzugter Name in einem anderen Datenbestand",
					R,
					"711",
					"Established Heading Linking Entry - Meeting Name");
		addTag(newTag);
		newTag =
			new Tag(
					"730",
					"022P",
					"Einheitstitel – Bevorzugter Name in einem anderen Datenbestand",
					R,
					"730",
					"Established Heading Linking Entry - Uniform Title");
		addTag(newTag);
		newTag =
			new Tag(
					"750",
					"041P",
					"Sachbegriff – Bevorzugte Benennung in einem anderen Datenbestand",
					R,
					"750",
					"Established Heading Linking Entry - Topical Term");
		addTag(newTag);
		newTag =
			new Tag(
					"751",
					"065P",
					"Geografikum – Bevorzugter Name in einem anderen Datenbestand",
					R,
					"751",
					"Established Heading Linking Entry - Geographic Name");
		addTag(newTag);
		newTag =
			new Tag(
					"797",
					"003@",
					"Interne Identifikationsnummer PPN",
					NR,
					"001; 003",
					"Control Number (Identifier)");
		addTag(newTag);
		newTag.addIndicator(new Indicator("-ohne-", '0', "", U, ""));
		
		newTag = new Tag(
						"901", 
						"047A/01", 
						"Mailbox", 
						R, 
						"912", 
						"");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, 'z', "Datum", NR, ""));
		newTag.addIndicator(new Indicator(null, 'b', "Absender/Empfänger", NR, ""));
		newTag.addIndicator(new Indicator(null, 'a', "Freitext", NR, ""));
		
		newTag =
			new Tag(
					"903",
					"047A/03",
					"Katalogisierende Institution",
					R,
					"040",
					"Cataloging Source");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, 'e', "ISIL des Urhebers", NR, ""));
		newTag.addIndicator(new Indicator(null, 'r', "ISIL der Verbundredaktion", NR, ""));
		
		newTag =
			new Tag(
					"913",
					"047C",
					"Alte Ansetzungsform",
					R,
					"913",
					"");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, 'S', "Normdatei (swd, gkd, pnd, est)", U, ""));
		newTag.addIndicator(new Indicator(null, 'i', "Indikator", U, ""));
		newTag.addIndicator(new Indicator(null, 'a', "Ansetzungsform", U, ""));
		newTag.addIndicator(new Indicator(null, '0', "Normnummer", U, ""));
		
		newTag =
			new Tag(
					"980",
					"070A/00",
					"Sortiername im Deutschen Exilarchiv",
					NR,
					"null",
					"");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, 'a', "Körperschaftsname, Gebietskörperschaftsname, Kongressname", NR, ""));
		newTag.addIndicator(new Indicator(null, 'n', "Zählung", R, ""));
		newTag.addIndicator(new Indicator(null, 'd', "Datum", NR, ""));
		newTag.addIndicator(new Indicator(null, 'c', "Ort", NR, ""));
		newTag.addIndicator(new Indicator(null, 'b', "Untergeordnete Körperschaft, untergeordnete Einheit eines Kongresses", R, ""));
		newTag.addIndicator(new Indicator(null, 'g', "Zusatz", R, ""));
		newTag.addIndicator(new Indicator(null, '4', "GND-Code für Beziehungen", NR, ""));
		newTag.addIndicator(new Indicator(null, '5', "Institution (=ISIL), die Feld in besonderer Art verwendet", R, ""));
		newTag.addIndicator(new Indicator(null, 'v', "Bemerkungen", R, ""));
		
		// wiederholbar!
		newTag = new Tag(
						"999", 
						"070B/09", 
						"Fehlermeldungen", 
						R, 
						"null", 
						"");
		addTag(newTag);
		newTag.addIndicator(new Indicator(null, 'a', "Bezug zu der gesuchten Relation", NR, ""));
		newTag.addIndicator(new Indicator(null, 'b', "Fehlermeldung", NR, ""));

		connect4XX();
		connect5XX();
		connect7XX();
		
	}
	
	private static void connect4XX() {
		final Tag tag4XX = new Tag("4XX", null, null, R, null, null);
		tag4XX.addIndicator(new Indicator(null, '4', "GND-Code für Beziehungen", NR, ""));
		tag4XX.addIndicator(new Indicator(null, '5', "Institution (=ISIL), die Feld in besonderer Art verwendet", R, ""));
		tag4XX.addIndicator(new Indicator(null, 'L', "Sprachcode bei nicht-lateinischen Schriftzeichen", NR, ""));
		tag4XX.addIndicator(new Indicator(null, 'T', "Feldzuordnung bei nicht- lateinischen Schriftzeichen", NR, ""));
		tag4XX.addIndicator(new Indicator(null, 'U', "Schriftcode bei nicht-lateinischen Schriftzeichen", NR, ""));
	
		Map<String, Tag> map4XX = pica3Map.subMap("400", "500");		
		Collection<Tag> tags4XX = map4XX.values();
		
		for (Tag tag : tags4XX) {
			String tagStr = "1" + tag.pica3.substring(1);
			Tag tag1XX = pica3Map.get(tagStr);
			tag.inherited.add(tag1XX);
			tag.inherited.add(tag4XX);
		}
	
	}
	
	private static void connect5XX() {
		final Tag tag5XX = new Tag("5XX", null, null, R, null, null);
		tag5XX.addIndicator(new Indicator(null, '9', "Verknüpfungsnummer", NR, ""));
		tag5XX.addIndicator(new Indicator(null, '8', "Expansion eines gefundenen Datensatzes", NR, ""));
		tag5XX.addIndicator(new Indicator(null, '4', "GND-Code für Beziehungen", NR, ""));
		tag5XX.addIndicator(new Indicator(null, '5', "Institution (=ISIL), die Feld in besonderer Art verwendet", R, ""));
		tag5XX.addIndicator(new Indicator(null, 'v', "Bemerkungen, Regelwerk", R, ""));
		tag5XX.addIndicator(new Indicator(null, 'X', "Anzeige-Relevanz", NR, ""));
		tag5XX.addIndicator(new Indicator(null, 'Y', "MO-Relevanz", R, ""));
		tag5XX.addIndicator(new Indicator(null, 'Z', "Zeitliche Gültigkeit", NR, ""));
		
		Map<String, Tag> map5XX = pica3Map.subMap("500", "600");		
		Collection<Tag> tags5XX = map5XX.values();
		
		for (Tag tag : tags5XX) {
			String tagStr = "1" + tag.pica3.substring(1);
			Tag tag1XX = pica3Map.get(tagStr);
			tag.inherited.add(tag5XX);
			tag.related = tag1XX;
		}
	}
	
	private static void connect7XX() {
		final Tag tag7XX = new Tag("7XX", null, null, R, null, null);
		tag7XX.addIndicator(new Indicator(null, 'u', "URI", R, ""));
		tag7XX.addIndicator(new Indicator(null, 'S', "ISIL der Referenz-Normdatei", NR, ""));
		tag7XX.addIndicator(new Indicator(null, '0', "Identifikationsnummer", NR, ""));
		tag7XX.addIndicator(new Indicator(null, '2', "Code der Quelle", NR, ""));
		tag7XX.addIndicator(new Indicator(null, '5', "Institution (=ISIL), die Feld in besonderer Art verwendet", R, ""));
		tag7XX.addIndicator(new Indicator(null, 'v', "Bemerkungen, Regelwerk", R, ""));
		tag7XX.addIndicator(new Indicator(null, 'L', "Sprachcode bei nicht-lateinischen Schriftzeichen", NR, ""));
		tag7XX.addIndicator(new Indicator(null, 'T', "Feldzuordnung bei nicht- lateinischen Schriftzeichen", NR, ""));
		tag7XX.addIndicator(new Indicator(null, 'U', "Schriftcode bei nicht-lateinischen Schriftzeichen", NR, ""));
	
		// um 797 auszuschliessen:
		Map<String, Tag> map7XX = pica3Map.subMap("700", "796");		
		Collection<Tag> tags7XX = map7XX.values();
		
		for (Tag tag : tags7XX) {
			String tagStr = "1" + tag.pica3.substring(1);
			Tag tag1XX = pica3Map.get(tagStr);
			tag.inherited.add(tag7XX);
			tag.inherited.add(tag1XX);
		}
	
	}

	//@formatter:on

	/**
	 * @param args nix.
	 */
	public static void main(final String[] args) {
		Triplett<Tag, String, String> triplett =
			parseTag("007K ƒagndƒ01024348822");
		System.err.println(triplett);

	}

}
